var n = null;
var LLParser = function () {
};
var r = LLParser.stats = {
    all: 0,
    copyIn: 0,
    parse: 0,
    constructOut: 0
};
var o = function (e) {
    return n.llparser_create_descriptor(e, 1);
};
var s = function (e, t) {
    var i = n.llparser_create_descriptor(e, 0);
    var a = false;
    '^' === t[0] && (a = true);
    for (var r = a ? 1 : 0; r < t.length; r++) {
        var o = t.charCodeAt(r);
        if ('-' === t[r + 1]) {
            var s = t.charCodeAt(r + 2);
            if (o <= s) {
                n.llparser_descriptor_add_range(i, o, s);
                r += 2;
            } else {
                n.llparser_descriptor_add_char(i, o);
            }
        } else
            n.llparser_descriptor_add_char(i, o);
    }
    a && n.llparser_descriptor_revert(i);
    return i;
};
LLParser.create = function (e, t, r) {
    n || (n = require('./LLParserHelp'));
    var l = new LLParser();
    r = r || 16384;
    var d = l._llp = n.llparser_create(r, 128, 128);
    var A = {};
    var c = {};
    var h = '';
    for (h in (A.ALL = n.llparser_create_descriptor(d, 0), n.llparser_descriptor_set_all(A.ALL), A.NULL = n.llparser_create_descriptor(d, 0), n.llparser_descriptor_set_nil(A.NULL), e))
        A[h] = o(d);
    for (h in e)
        for (var u = e[h], p = A[h], g = 0; g < u.length; g++) {
            var _ = u[g].id;
            var f = u[g].states;
            var v = [];
            for (var w = 0; w < f.length; w++) {
                var m = f[w];
                A[m] || (A[m] = s(d, m));
                v.push(A[m]);
            }
            var I = 0;
            if ('_raw' === _) {
                I = 1;
            } else {
                if ('_jump' === _) {
                    I = 65536;
                } else {
                    '_blank' === _ && (I = 65537);
                }
            }
            var b = n.llparser_add_rule(d, I, p, v.length, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
            0 === I && (c[b] = t[_]);
        }
    n.llparser_prepare(d);
    l._inputPtr = n.llparser_get_input_buffer(d);
    l._resultPtr = n.llparser_get_result(d);
    l._stateIdMap = A;
    l._ruleCbMap = c;
    l._charCountLimit = r;
    return l;
};
LLParser.prototype.parse = function (e, t) {
    var i = Date.now();
    !function (e, t, i, n) {
        var a = n > e.length ? e.length : n;
        for (var r = 0; r < a; r++)
            t[i + r] = e.charCodeAt(r);
        t[i + a] = 0;
    }(t, new Uint16Array(n.memory.buffer), this._inputPtr >> 1, this._charCountLimit);
    r.copyIn = r.copyIn + Date.now() - i;
    i = Date.now();
    var a = n.llparser_parse(this._llp, this._stateIdMap[e]);
    r.parse = r.parse + Date.now() - i;
    i = Date.now();
    if (a)
        throw new Error('Parsing failed at character position ' + (a - 1) + ' near "' + t.slice(a - 20, a) + '"');
    var o = function (e, t, i, n, a) {
        var r = [];
        var o = {
            i: 0,
            r: 0,
            n: false,
            cc: -1,
            c: []
        };
        var s = o;
        var l = a.pos;
        var d = false;
        var A = false;
        for (var c = false;;) {
            var h = t[l];
            var u = t[l + 1];
            if (u < 0) {
                A = true;
                u = -u - 1;
            } else {
                A = false;
            }
            if (h >= 0) {
                c = true;
                var p = i.slice(h, u);
                s.c.push(p);
                d = A;
            } else {
                if (-1 === h && 0 === u)
                    break;
                c = false;
                var g = -h;
                var _ = u;
                var f = {
                    i: s.c.length - (d ? 1 : 0),
                    r: g,
                    n: A,
                    cc: _,
                    c: []
                };
                if (d) {
                    var v = s.c.length - 1;
                    var w = s.c[v];
                    f.c.push(w);
                    s.c[v] = f;
                } else
                    s.c.push(f);
                r.push(s);
                s = f;
                d = false;
            }
            if (!c || !d)
                for (; s.c.length === s.cc;) {
                    d = s.n;
                    var m = r.pop();
                    m.c[s.i] = n[s.r].call(e, s.c);
                    s = m;
                    if (d)
                        break;
                }
            l += 2;
        }
        return o.c[0];
    }(this, new Int32Array(n.memory.buffer), t, this._ruleCbMap, { pos: this._resultPtr >> 2 });
    r.constructOut = r.constructOut + Date.now() - i;
    return o;
};
LLParser.prototype.destroy = function () {
    n.llparser_destroy(this._llp);
};
module.exports = LLParser;
